package config

import (
	"errors"
	"fmt"
	"os"
	"path/filepath"
	"strings"
	"sync"

	"gopkg.in/yaml.v3"
)

// Config 存储整个应用程序的配置
type Config struct {
	mu      sync.RWMutex
	configs map[string]interface{}
}

var (
	defaultConfig *Config
	once          sync.Once
)

// 初始化默认配置实例
func init() {
	defaultConfig = &Config{
		configs: make(map[string]interface{}),
	}
}

// LoadConfig 加载configs目录下的所有YAML配置文件
func LoadConfig(configDir string) error {
	var err error
	once.Do(func() {
		err = defaultConfig.loadAllConfigs(configDir)
	})
	return err
}

// Get 获取配置项，支持点分隔路径访问嵌套配置
func Get(path string) (interface{}, error) {
	return defaultConfig.Get(path)
}

// GetString 获取字符串类型的配置项
func GetString(path string) (string, error) {
	val, err := Get(path)
	if err != nil {
		return "", err
	}

	strVal, ok := val.(string)
	if !ok {
		return "", fmt.Errorf("配置项 %s 不是字符串类型", path)
	}

	return strVal, nil
}

// GetInt 获取整型配置项
func GetInt(path string) (int, error) {
	val, err := Get(path)
	if err != nil {
		return 0, err
	}

	// YAML解析可能返回不同的数值类型
	switch v := val.(type) {
	case int:
		return v, nil
	case int64:
		return int(v), nil
	case float64:
		return int(v), nil
	default:
		return 0, fmt.Errorf("配置项 %s 不是整数类型", path)
	}
}

// GetBool 获取布尔类型配置项
func GetBool(path string) (bool, error) {
	val, err := Get(path)
	if err != nil {
		return false, err
	}

	boolVal, ok := val.(bool)
	if !ok {
		return false, fmt.Errorf("配置项 %s 不是布尔类型", path)
	}

	return boolVal, nil
}

// Get 从Config实例中获取配置
func (c *Config) Get(path string) (interface{}, error) {
	c.mu.RLock()
	defer c.mu.RUnlock()

	parts := strings.Split(path, ".")
	current := c.configs

	for i, part := range parts {
		// 处理最后一个部分
		if i == len(parts)-1 {
			if val, ok := current[part]; ok {
				return val, nil
			}
			return nil, fmt.Errorf("配置项 %s 不存在", path)
		}

		// 处理中间路径
		next, ok := current[part]
		if !ok {
			return nil, fmt.Errorf("配置路径 %s 不存在", strings.Join(parts[:i+1], "."))
		}

		// 确保中间节点是一个映射
		nextMap, ok := next.(map[string]interface{})
		if !ok {
			return nil, fmt.Errorf("配置路径 %s 不是一个对象", strings.Join(parts[:i+1], "."))
		}

		current = nextMap
	}

	return nil, errors.New("无效的配置路径")
}

// loadAllConfigs 加载指定目录下的所有YAML配置文件
func (c *Config) loadAllConfigs(configDir string) error {
	c.mu.Lock()
	defer c.mu.Unlock()

	// 检查配置目录是否存在
	info, err := os.Stat(configDir)
	if err != nil {
		return fmt.Errorf("无法访问配置目录 %s: %w", configDir, err)
	}

	if !info.IsDir() {
		return fmt.Errorf("%s 不是一个目录", configDir)
	}

	// 遍历配置目录中的所有文件
	err = filepath.Walk(configDir, func(path string, info os.FileInfo, err error) error {
		if err != nil {
			return err
		}

		// 跳过目录和非YAML文件
		if info.IsDir() || (!strings.HasSuffix(info.Name(), ".yaml") && !strings.HasSuffix(info.Name(), ".yml")) {
			return nil
		}

		// 读取并解析YAML文件
		data, err := os.ReadFile(path)
		if err != nil {
			return fmt.Errorf("读取配置文件 %s 失败: %w", path, err)
		}

		var config map[string]interface{}
		if err := yaml.Unmarshal(data, &config); err != nil {
			return fmt.Errorf("解析配置文件 %s 失败: %w", path, err)
		}

		// 提取文件名作为配置键(不包含扩展名)
		baseName := filepath.Base(path)
		configName := strings.TrimSuffix(baseName, filepath.Ext(baseName))

		// 存储配置
		c.configs[configName] = config

		return nil
	})

	if err != nil {
		return fmt.Errorf("加载配置文件时出错: %w", err)
	}

	return nil
}

var TablePrefix = ""

func GetTablePrefix() string {
	return TablePrefix
}

func SetTablePrefix(prefix string) {
	TablePrefix = prefix
}
